package com.zhentao.service.impl;

import com.alibaba.fastjson2.JSON;
import com.zhentao.config.AmapConfig;
import com.zhentao.dto.*;
import com.zhentao.service.AmapService;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * 高德地图服务实现类
 */
@Service
@Slf4j
public class AmapServiceImpl implements AmapService {
    
    @Autowired
    private AmapConfig amapConfig;
    
    private final CloseableHttpClient httpClient = HttpClients.createDefault();
    
    @Override
    public GeocodeResponse geocode(GeocodeRequest request) {
        try {
            Map<String, String> params = new HashMap<>();
            params.put("key", amapConfig.getWebApiKey());
            params.put("address", request.getAddress());
            if (StringUtils.hasText(request.getCity())) {
                params.put("city", request.getCity());
            }
            params.put("output", request.getOutput());
            
            String url = buildUrl(amapConfig.getBaseUrl() + "/v3/geocode/geo", params);
            String response = doGet(url);
            
            log.info("地理编码响应: {}", response);
            return JSON.parseObject(response, GeocodeResponse.class);
            
        } catch (Exception e) {
            log.error("地理编码失败", e);
            GeocodeResponse errorResponse = new GeocodeResponse();
            errorResponse.setStatus("0");
            errorResponse.setInfo("地理编码失败: " + e.getMessage());
            return errorResponse;
        }
    }
    
    @Override
    public RegeocodeResponse regeocode(RegeocodeRequest request) {
        try {
            Map<String, String> params = new HashMap<>();
            params.put("key", amapConfig.getWebApiKey());
            params.put("location", request.getLocation());
            if (StringUtils.hasText(request.getPoitype())) {
                params.put("poitype", request.getPoitype());
            }
            params.put("radius", String.valueOf(request.getRadius()));
            params.put("extensions", request.getExtensions());
            params.put("output", request.getOutput());
            
            String url = buildUrl(amapConfig.getBaseUrl() + "/v3/geocode/regeo", params);
            String response = doGet(url);
            
            log.info("逆地理编码响应: {}", response);
            return JSON.parseObject(response, RegeocodeResponse.class);
            
        } catch (Exception e) {
            log.error("逆地理编码失败", e);
            RegeocodeResponse errorResponse = new RegeocodeResponse();
            errorResponse.setStatus("0");
            errorResponse.setInfo("逆地理编码失败: " + e.getMessage());
            return errorResponse;
        }
    }
    
    @Override
    public AmapPoiSearchResponse searchNearbyPoi(AmapPoiSearchRequest request) {
        try {
            Map<String, String> params = new HashMap<>();
            params.put("key", amapConfig.getWebApiKey());
            params.put("location", request.getLocation());
            if (StringUtils.hasText(request.getKeywords())) {
                params.put("keywords", request.getKeywords());
            }
            if (StringUtils.hasText(request.getTypes())) {
                params.put("types", request.getTypes());
            }
            params.put("radius", String.valueOf(request.getRadius()));
            params.put("sortrule", request.getSortrule());
            params.put("offset", String.valueOf(request.getOffset()));
            params.put("page", String.valueOf(request.getPage()));
            params.put("output", request.getOutput());
            
            String url = buildUrl(amapConfig.getBaseUrl() + "/v3/place/around", params);
            String response = doGet(url);
            
            log.info("POI搜索响应: {}", response);
            return JSON.parseObject(response, AmapPoiSearchResponse.class);
            
        } catch (Exception e) {
            log.error("POI搜索失败", e);
            AmapPoiSearchResponse errorResponse = new AmapPoiSearchResponse();
            errorResponse.setStatus("0");
            errorResponse.setInfo("POI搜索失败: " + e.getMessage());
            return errorResponse;
        }
    }
    
    @Override
    public Integer calculateDistance(String origin, String destination) {
        try {
            Map<String, String> params = new HashMap<>();
            params.put("key", amapConfig.getWebApiKey());
            params.put("origins", origin);
            params.put("destination", destination);
            params.put("type", "1"); // 1表示驾车距离
            
            String url = buildUrl(amapConfig.getBaseUrl() + "/v3/distance", params);
            String response = doGet(url);
            
            log.info("距离计算响应: {}", response);
            Map<String, Object> result = JSON.parseObject(response, Map.class);
            
            if ("1".equals(result.get("status"))) {
                Object data = result.get("results");
                if (data != null) {
                    // 解析距离结果
                    return parseDistanceResult(data);
                }
            }
            
            return -1; // 计算失败
            
        } catch (Exception e) {
            log.error("距离计算失败", e);
            return -1;
        }
    }
    
    @Override
    public RegeocodeResponse getLocationInfo(Double latitude, Double longitude) {
        RegeocodeRequest request = new RegeocodeRequest();
        request.setLocation(longitude + "," + latitude); // 高德地图使用"经度,纬度"格式
        request.setRadius(1000);
        request.setExtensions("all");
        
        return regeocode(request);
    }
    
    /**
     * 构建请求URL
     */
    private String buildUrl(String baseUrl, Map<String, String> params) {
        StringBuilder urlBuilder = new StringBuilder(baseUrl);
        urlBuilder.append("?");
        
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (entry.getValue() != null) {
                urlBuilder.append(entry.getKey())
                        .append("=")
                        .append(URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8))
                        .append("&");
            }
        }
        
        // 移除最后一个&
        if (urlBuilder.charAt(urlBuilder.length() - 1) == '&') {
            urlBuilder.setLength(urlBuilder.length() - 1);
        }
        
        return urlBuilder.toString();
    }
    
    /**
     * 执行GET请求
     */
    private String doGet(String url) throws IOException {
        HttpGet httpGet = new HttpGet(url);
        
        try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
            HttpEntity entity = response.getEntity();
            return EntityUtils.toString(entity, StandardCharsets.UTF_8);
        }
    }
    
    /**
     * 解析距离计算结果
     */
    private Integer parseDistanceResult(Object data) {
        try {
            if (data instanceof String) {
                // 如果是字符串，尝试解析
                Map<String, Object> result = JSON.parseObject((String) data, Map.class);
                if (result.containsKey("distance")) {
                    return Integer.parseInt(result.get("distance").toString());
                }
            } else if (data instanceof Map) {
                // 如果是Map，直接获取
                Map<String, Object> result = (Map<String, Object>) data;
                if (result.containsKey("distance")) {
                    return Integer.parseInt(result.get("distance").toString());
                }
            }
        } catch (Exception e) {
            log.error("解析距离结果失败", e);
        }
        return -1;
    }
}
